﻿Imports System
Imports System.Text
Imports System.Xml
Imports System.Collections.Generic
Imports System.IO
Imports System.Net.Mail
Imports System.Web
Imports System.Net

Namespace MyspaceToolkit

    Public Class MyspaceClient



    End Class

    ''' <summary>
    ''' HttpPostUtility is a helper class that handles the posting of the api variables to the myspace service endpoint.
    ''' </summary>
    ''' <remarks>
    ''' This class will eventually be called by methods inside of the MyspaceClient class and will not be used directly.
    ''' </remarks>
    Public Class HttpPostUtility

        ''' <summary>
        ''' RequestMethod type determines which API Method should be called.
        ''' </summary>
        ''' <remarks>
        ''' </remarks>
        Public Enum RequestMethod
            GetProfile = 0
            GetBasicProfile = 1
            GetFriends = 2
            GetFriendById = 3
            GetAlbums = 4
            GetAlbumById = 5
            GetAlbumPhotosById = 6
            GetUserPhotos = 7
            GetPhotoById = 8
            GetUserInterests = 9
            GetUserDetails = 10
            GetUserVideos = 11
            GetVideoById = 12
            GetUserStatus = 13
            GetUserMood = 14
        End Enum

        ''' <summary>
        ''' RequestMode determines the method for the request. Currently this value is examined upon request, and by default querystrings are used to make all requests.
        ''' </summary>
        ''' <remarks>
        ''' </remarks>
        Public Enum RequestMode
            AuthHeaders
            QueryString
        End Enum

        ''' <summary>
        ''' ResponseType determines the content type of the response. There will be a parser class to parse either the xml or json response
        ''' and serialize the values into an object.
        ''' </summary>
        ''' <remarks>
        ''' </remarks>
        Public Enum ResponseType
            JSON
            XML
        End Enum

        ''' <summary>
        ''' MyspaceRequest is used as the base request class to contain important values required to make a successful API request.
        ''' </summary>
        ''' <remarks>
        ''' </remarks>
        Public Class MyspaceRequest

            Private _requestMethod As RequestMethod
            Private _requestMode As RequestMode
            Private _responseType As ResponseType
            Private _assetId As String
            Private _consumerKey As String
            Private _consumerSecret As String
            Private _token As String
            Private _tokenSecret As String
            Private _baseApiUrlHost As String
            Private _apiVersion As String
            Private _userId As String
            Private _urlParameters As New Hashtable
            Private _pageNumber As String
            Private _pageSize As String
            Private _listType As ListType

            ''' <summary>
            ''' ListType determines the type of response when executing the GetFriends method.
            ''' </summary>
            ''' <remarks>
            ''' </remarks>
            Public Enum ListType
                none
                top
                online
            End Enum

            ''' <summary>
            ''' APIVersion is what version of the myspace API you would like to use.
            ''' </summary>
            ''' <value>String</value>
            ''' <returns>String</returns>
            ''' <remarks></remarks>
            Public Property APIversion() As String
                Get
                    Return _apiVersion
                End Get
                Set(ByVal value As String)
                    _apiVersion = value
                End Set
            End Property

            ''' <summary>
            ''' AssetID is used for assets such as: PhotoId, Friend/User ID, VideoId, AlbumId etc. 
            ''' </summary>
            ''' <value>String</value>
            ''' <returns>String</returns>
            ''' <remarks></remarks>
            Public Property AssetID() As String
                Get
                    Return _assetId
                End Get
                Set(ByVal value As String)
                    _assetId = value
                End Set
            End Property

            ''' <summary>
            ''' BaseApiUrlHost is used for the myspace service endpoint address to make calls.
            ''' </summary>
            ''' <value>String</value>
            ''' <returns>String</returns>
            ''' <remarks></remarks>
            Public Property BaseApiUrlHost() As String
                Get
                    Return _baseApiUrlHost
                End Get
                Set(ByVal value As String)
                    _baseApiUrlHost = value
                End Set
            End Property

            ''' <summary>
            ''' ConsumerKey is the key provided to you once you have created an application inside of the Myspace Developer Platform (MDP).
            ''' </summary>
            ''' <value>String</value>
            ''' <returns>String</returns>
            ''' <remarks></remarks>
            Public Property ConsumerKey() As String
                Get
                    Return _consumerKey
                End Get
                Set(ByVal value As String)
                    _consumerKey = value
                End Set
            End Property

            ''' <summary>
            ''' ConsumerSecret is the secret value provided to you ocne you have created an application inside of the MDP.
            ''' </summary>
            ''' <value>String</value>
            ''' <returns>String</returns>
            ''' <remarks></remarks>
            Public Property ConsumerSecret() As String
                Get
                    Return _consumerSecret
                End Get
                Set(ByVal value As String)
                    _consumerSecret = value
                End Set
            End Property

            ''' <summary>
            ''' ResponseListType is used specifically for when calling GetFriends to determine the type of friends to return.
            ''' <example>
            ''' ResponseListType rlt = new ResponseListType();
            ''' rlt.none | rlt.top | rlt.online;
            ''' </example>
            ''' </summary>
            ''' <value>ListType</value>
            ''' <returns>ListType</returns>
            ''' <remarks></remarks>
            Public Property ResponseListType() As ListType
                Get
                    Return _listType
                End Get
                Set(ByVal value As ListType)
                    _listType = value
                End Set
            End Property

            ''' <summary>
            ''' ResponsePageNumber is used specifically for when calling GetFriends to specify the page number to return.
            ''' </summary>
            ''' <value>String</value>
            ''' <returns>String</returns>
            ''' <remarks></remarks>
            Public Property ResponsePageNumber() As String
                Get
                    Return _pageNumber
                End Get
                Set(ByVal value As String)
                    _pageNumber = value
                End Set
            End Property

            ''' <summary>
            ''' ResponsePageNumber is used specifically for when calling GetFriends to specify the page size to be returned.
            ''' </summary>
            ''' <value>String</value>
            ''' <returns>String</returns>
            ''' <remarks></remarks>
            Public Property ResponsePageSize() As String
                Get
                    Return _pageSize
                End Get
                Set(ByVal value As String)
                    _pageSize = value
                End Set
            End Property

            ''' <summary>
            ''' RequestMethod is the specific endpoint method to be invoked to return a result. Such as GetFriends, GetPhotoAlbums etc.
            ''' </summary>
            ''' <value>RequestMethod</value>
            ''' <returns>RequestMethod</returns>
            ''' <remarks></remarks>
            Public Property RequestMethod() As RequestMethod
                Get
                    Return _requestMethod
                End Get
                Set(ByVal value As RequestMethod)
                    _requestMethod = value
                End Set
            End Property

            ''' <summary>
            ''' RequestMode is the mode for the request to go out. Currently this property is ignored and QueryStrings is always used.
            ''' This will be implemented in the next version of this toolkit.
            ''' </summary>
            ''' <value>RequestMode - AuthHeaders | Querystring</value>
            ''' <returns>RequestMode</returns>
            ''' <remarks></remarks>
            Public Property RequestMode() As RequestMode
                Get
                    Return _requestMode
                End Get
                Set(ByVal value As RequestMode)
                    _requestMode = value
                End Set
            End Property

            ''' <summary>
            ''' ResponseType is used to the determine the response content from an API request.
            ''' </summary>
            ''' <value>ResponseType - XML | JSON</value>
            ''' <returns>ResponseType</returns>
            ''' <remarks></remarks>
            Public Property ResponseType() As ResponseType
                Get
                    Return _responseType
                End Get
                Set(ByVal value As ResponseType)
                    _responseType = value
                End Set
            End Property

            ''' <summary>
            ''' Token is the token value that would be returned/provided by a service provider implementing the OAuth routine. Currently myspace doesn't use this method.
            ''' </summary>
            ''' <value>String</value>
            ''' <returns>String</returns>
            ''' <remarks></remarks>
            Public Property Token() As String
                Get
                    Return _token
                End Get
                Set(ByVal value As String)
                    _token = value
                End Set
            End Property

            ''' <summary>
            ''' TokenSecret is the token secret that would be returned/provided by a service provider implementing the OAuth routine. Currently myspace doesn't use this method.
            ''' </summary>
            ''' <value>String</value>
            ''' <returns>String</returns>
            ''' <remarks></remarks>
            Public Property TokenSecret() As String
                Get
                    Return _tokenSecret
                End Get
                Set(ByVal value As String)
                    _tokenSecret = value
                End Set
            End Property

            ''' <summary>
            ''' UserId would be the myspace user ID of the person who has your application installed and provides the ability use the API to query their account
            ''' from an external system, such as a website you create.
            ''' </summary>
            ''' <value>String</value>
            ''' <returns>String</returns>
            ''' <remarks></remarks>
            Public Property UserId() As String
                Get
                    Return _userId
                End Get
                Set(ByVal value As String)
                    _userId = value
                End Set
            End Property

            ''' <summary>
            ''' UrlParameters is used to facilitate the ability to add additionally parameters to the URL. This method might be changed in the future to be more robust.
            ''' Currently it is only necessary to enable the paging ability with a GetFriends response.
            ''' </summary>
            ''' <value>Hashtable</value>
            ''' <returns>Hashtable</returns>
            ''' <remarks></remarks>
            Public Property UrlParameters() As Hashtable
                Get
                    Return _urlParameters
                End Get
                Set(ByVal value As Hashtable)
                    _urlParameters = value
                End Set
            End Property

        End Class

        ''' <summary>
        ''' MakeRequest configures a request to be posted to the Myspace REST API interface based on the parameters passed in.
        ''' </summary>
        ''' <param name="myspaceRequest">MyspaceRequest property is used to hold all the necessary configuration values for a myspace rest api request.</param>
        ''' <returns>String - XML or JSON</returns>
        ''' <remarks>This method will be called internally and there will be a separate helper class to parse the response.</remarks>
        Public Function MakeRequest(ByVal myspaceRequest As MyspaceRequest) As String

            Dim ReturnValue As String
            Dim webRequest As HttpWebRequest
            Dim responseReader As StreamReader
            Dim requestWriter As StreamWriter
            Dim responseData As String = ""

            If Not myspaceRequest.ResponsePageNumber Is Nothing Then

                myspaceRequest.UrlParameters.Add("page", myspaceRequest.ResponsePageNumber)
                myspaceRequest.UrlParameters.Add("page_size", myspaceRequest.ResponsePageSize)
                If myspaceRequest.ResponseListType.ToString().ToLower() <> "none" Then
                    myspaceRequest.UrlParameters.Add("list", myspaceRequest.ResponseListType.ToString())
                End If

            End If

            Dim methodPath As String = DefineRequestPath(myspaceRequest.RequestMethod.ToString(), myspaceRequest.AssetID)
            Dim requestUrl As String = BuildRequestURL(myspaceRequest.APIversion, myspaceRequest.BaseApiUrlHost, myspaceRequest.ResponseType, myspaceRequest.UserId, methodPath)
            Dim postData As String = BuildParameters(myspaceRequest.APIversion, requestUrl, myspaceRequest.ConsumerKey, myspaceRequest.ConsumerSecret, myspaceRequest.Token, myspaceRequest.TokenSecret, "GET", myspaceRequest.UrlParameters)
            Dim cookies As CookieContainer = New CookieContainer
            webRequest = Net.WebRequest.Create(requestUrl & postData)
            webRequest.Method = "GET"
            webRequest.ContentType = "application/x-www-form-urlencoded"
            'webRequest.CookieContainer = cookies

            'Eventually we might implement post data once myspace has provided
            'methods that work with post, currently there are only retrieve/get methods.
            '-------------------------------------------------------------
            'requestWriter = New StreamWriter(webRequest.GetRequestStream)
            'requestWriter.Write(postData)
            'requestWriter.Close()

            Try
                responseReader = New StreamReader(webRequest.GetResponse.GetResponseStream)
                responseData = responseReader.ReadToEnd
                responseReader.Close()
                webRequest.GetResponse.Close()
            Catch ex As Exception
                responseData = ex.Message
            End Try

            ReturnValue = responseData

            Return ReturnValue
        End Function

        ''' <summary>
        ''' BuildRequestUrl is a private method used as helper to create the base url.
        ''' </summary>
        ''' <param name="APIversion">Version of the Myspace API</param>
        ''' <param name="BaseUrl">BaseUrl is the root hostname for the request.</param>
        ''' <param name="ResponseTy">ResponseTy is the extension for the respone (JSON or XML)</param>
        ''' <param name="UserId">UserId is the user id of the user to retrieve information/data from.</param>
        ''' <param name="MethodPath">MethodPath determines the specific service endpoint to make the request.</param>
        ''' <returns>String</returns>
        ''' <remarks></remarks>
        Private Function BuildRequestURL(ByVal APIversion As String, ByVal BaseUrl As String, ByVal ResponseTy As ResponseType, ByVal UserId As String, ByVal MethodPath As String) As String
            Dim ReturnValue As New StringBuilder

            ReturnValue.Append("http://")
            ReturnValue.Append(BaseUrl & "/")
            ReturnValue.Append(APIversion & "/")
            ReturnValue.Append("users/")
            ReturnValue.Append(UserId)
            ReturnValue.Append(MethodPath)
            ReturnValue.Append("." & ResponseTy.ToString().ToLower())

            Return ReturnValue.ToString
        End Function

        ''' <summary>
        ''' BuildParameters is a private method used as helper to create the querystring values for the request. This method utilizes the OAuth class developed by Eran Sandler (http://eran.sandler.co.il/).
        ''' </summary>
        ''' <param name="APIversion">Version of the Myspace API</param>
        ''' <param name="requestUrl">Request URL is the url to make the request to.</param>
        ''' <param name="consumerKey">ConsumerKey is the key provided to you once you have created an application inside of the Myspace Developer Platform (MDP).</param>
        ''' <param name="consumerSecret">ConsumerSecret is the secret provided to you once you have created an application inside of the Myspace Developer Platform (MDP).</param>
        ''' <param name="Token">Token is the token value that would be returned/provided by a service provider implementing the OAuth routine. Currently myspace doesn't use this method.</param>
        ''' <param name="TokenSecret">TokenSecret is the token value that would be returned/provided by a service provider implementing the OAuth routine. Currently myspace doesn't use this method.</param>
        ''' <param name="MethodType">MethodType is the type for the method (GET, POST, DELETE etc.) currently only GET is supported by MDP.</param>
        ''' <param name="UrlParameters">UrlParameters are the additionaly parameters required for certain API calls.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function BuildParameters(ByVal APIversion As String, ByVal requestUrl As String, ByVal consumerKey As String, ByVal consumerSecret As String, ByVal Token As String, ByVal TokenSecret As String, ByVal MethodType As String, ByVal UrlParameters As Hashtable) As String
            Dim OAuth1 As New OAuth.OAuthBase()
            Dim addParams As New StringBuilder

            If UrlParameters.Count > 0 Then
                Dim icount As Integer = 1
                For Each item As DictionaryEntry In UrlParameters
                    If icount = 1 Then
                        addParams.Append("?" & item.Key.ToString() & "=")
                        addParams.Append(OAuth1.UrlEncode(item.Value.ToString()))
                    Else
                        addParams.Append("&" & item.Key.ToString() & "=")
                        addParams.Append(OAuth1.UrlEncode(item.Value.ToString()))
                    End If
                    icount += 1
                Next
            End If

            Dim uri1 As New Uri(requestUrl & addParams.ToString())
            Dim nonce As String = System.Guid.NewGuid().ToString()
            Dim timestamp As String = OAuth1.GenerateTimeStamp()
            Dim signature As String = OAuth1.GenerateSignature(uri1, consumerKey, consumerSecret, Token, TokenSecret, MethodType, timestamp, nonce, OAuth.OAuthBase.SignatureTypes.HMACSHA1)
            Dim ReturnValue As New StringBuilder

            ReturnValue.Append("?oauth_consumer_key=")
            ReturnValue.Append(OAuth1.UrlEncode(consumerKey))
            ReturnValue.Append("&oauth_nonce=")
            ReturnValue.Append(OAuth1.UrlEncode(nonce))
            ReturnValue.Append("&oauth_signature=")
            ReturnValue.Append(OAuth1.UrlEncode(signature))
            ReturnValue.Append("&oauth_signature_method=HMAC-SHA1")
            ReturnValue.Append("&oauth_timestamp=")
            ReturnValue.Append(timestamp)
            ReturnValue.Append("&oauth_token=")
            ReturnValue.Append(Token)
            ReturnValue.Append("&oauth_version=")
            ReturnValue.Append(GetNumericAPIVersion(APIversion))
            If UrlParameters.Count > 0 Then
                For Each item As DictionaryEntry In UrlParameters
                    ReturnValue.Append("&" & item.Key.ToString() & "=")
                    ReturnValue.Append(OAuth1.UrlEncode(item.Value.ToString()))
                Next
            End If

            Return ReturnValue.ToString
        End Function

        ''' <summary>
        ''' Defines the request path based on the input values.
        ''' </summary>
        ''' <param name="RequestMethodType">RequestMethodType is the requestmethod to determine the right endpoint address.</param>
        ''' <param name="OptionalAssetId">OptionAssetId is used to provide additional information about specific calls (such as: GetAlbumById).</param>
        ''' <returns>String</returns>
        ''' <remarks></remarks>
        Private Function DefineRequestPath(ByVal RequestMethodType As String, ByVal OptionalAssetId As String) As String
            Dim ReturnValue As String = ""

            Select Case RequestMethodType.ToLower()
                Case "getprofile"
                    ReturnValue = "/profile"
                Case "getbasicprofile"
                    ReturnValue = ""
                Case "getfriends"
                    ReturnValue = "/friends"
                Case "getfriendbyid"
                    ReturnValue = "/friends/" & OptionalAssetId
                Case "getalbums"
                    ReturnValue = "/albums"
                Case "getalbumbyid"
                    ReturnValue = "/albums/" & OptionalAssetId
                Case "getalbumphotosbyid"
                    ReturnValue = "/albums/" & OptionalAssetId & "/photos"
                Case "getuserphotos"
                    ReturnValue = "/photos"
                Case "getphotobyid"
                    ReturnValue = "/photos/" & OptionalAssetId
                Case "getuserinterests"
                    ReturnValue = "/interests"
                Case "getuserdetails"
                    ReturnValue = "/details"
                Case "getuservideos"
                    ReturnValue = "/videos"
                Case "getvideobyid"
                    ReturnValue = "/videos/" & OptionalAssetId
                Case "getuserstatus"
                    ReturnValue = "/status"
                Case "getusermood"
                    ReturnValue = "/mood"
                Case Else
                    ReturnValue = ""
            End Select

            Return ReturnValue
        End Function

        ''' <summary>
        ''' GetNumericAPIVersion is a helper function to provide the API version in a numeric/double string format.
        ''' </summary>
        ''' <param name="version">Version is the string version value.</param>
        ''' <returns>String</returns>
        ''' <remarks>This method is more than likely not a good way to determine this value. Expect it to change in the future.</remarks>
        Private Function GetNumericAPIVersion(ByVal version As String) As String
            Dim ReturnValue As String = ""

            Select Case version
                Case "v1"
                    ReturnValue = "1.0"
                Case Else
                    ReturnValue = "1.0"
            End Select

            Return ReturnValue
        End Function

    End Class

End Namespace
